{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**第二章 面向对象编程 课后题**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 巩固题"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2.4) 编写一个Python类的Flower。该类有str、int、float类型的三种实例变量，分别代表花的名字、花瓣的数量和价格。该类必须包含一个构造函数，该构造函数给每个变量初始化一个合适的值。该类应该包含设置和检索每种类型值的方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T06:40:01.997666Z",
     "start_time": "2019-05-21T06:40:01.991698Z"
    }
   },
   "outputs": [],
   "source": [
    "class Flower:\n",
    "    '''three variables - str name, int number, float cost'''\n",
    "    def __init__(self, name='Rose', number=0, cost=0):\n",
    "        self._name = name \n",
    "        self._number = number\n",
    "        self._cost = cost\n",
    "    \n",
    "    def __getname__(self):\n",
    "        return self._name\n",
    "    \n",
    "    def __getnumber__(self):\n",
    "        return self._number\n",
    "    \n",
    "    def __getcost__(self):\n",
    "        return self._cost\n",
    "    \n",
    "    def __setname__(self, name):\n",
    "        self._name = name\n",
    "        return self._name\n",
    "    \n",
    "    def __setnumber__(self, number):\n",
    "        self._number = number\n",
    "        return self._number\n",
    "    \n",
    "    def __setcost__(self, cost):\n",
    "        self._cost = cost\n",
    "        return self._cost"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T06:43:39.314184Z",
     "start_time": "2019-05-21T06:43:39.309196Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "rose\n",
      "100\n",
      "10000\n"
     ]
    }
   ],
   "source": [
    "rose = Flower('rose', 100, 10000)\n",
    "print(rose.__getname__())\n",
    "print(rose.__getnumber__())\n",
    "print(rose.__getcost__())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T06:45:56.161738Z",
     "start_time": "2019-05-21T06:45:56.156751Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "lotus\n",
      "10\n",
      "99\n"
     ]
    }
   ],
   "source": [
    "rose.__setname__('lotus')\n",
    "rose.__setnumber__(10)\n",
    "rose.__setcost__(99)\n",
    "print(rose.__getname__())\n",
    "print(rose.__getnumber__())\n",
    "print(rose.__getcost__())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2.9)实现2.3.3节Vector类的__sub__方法，使表达式u-v返回一个代表两矢量间差异的新矢量实例。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T07:12:04.080816Z",
     "start_time": "2019-05-21T07:12:04.075829Z"
    }
   },
   "outputs": [],
   "source": [
    "class Vector:\n",
    "    \n",
    "    def __init__(self, d):\n",
    "        self._coords = [0]*d\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self._coords)\n",
    "    \n",
    "    def __getitem__(self, j):\n",
    "        return self._coords[j]\n",
    "    \n",
    "    def __setitem__(self, j, val):\n",
    "        self._coords[j] = val\n",
    "    \n",
    "    def __sub__(self, other):\n",
    "        if self.__len__() != len(other):\n",
    "            raise ValueError('Dimensions must agree!!')\n",
    "        else:\n",
    "            result = Vector(self.__len__())\n",
    "            for i in range(self.__len__()):\n",
    "                result[i] = self[i] - other[i]\n",
    "            return result\n",
    "    '''There are many other functions to write'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T07:14:17.748806Z",
     "start_time": "2019-05-21T07:14:17.743820Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-1, 0, 1, 2]\n"
     ]
    }
   ],
   "source": [
    "v = Vector(4)\n",
    "for i in range(4):\n",
    "    v[i] = 2*i\n",
    "subone = [1,2,3,4]\n",
    "result = v.__sub__(subone)\n",
    "print([result.__getitem__(i) for i in range(4)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2.10)实现2.3.3节Vector类的__neg__方法，使表达式-v返回一个新的矢量实例。新矢量v的坐标值都是负值。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T07:42:52.941063Z",
     "start_time": "2019-05-21T07:42:52.933083Z"
    }
   },
   "outputs": [],
   "source": [
    "class Vector:\n",
    "    \n",
    "    def __init__(self, d):\n",
    "        self._coords = [0]*d\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self._coords)\n",
    "    \n",
    "    def __getitem__(self, j):\n",
    "        return self._coords[j]\n",
    "    \n",
    "    def __setitem__(self, j, val):\n",
    "        self._coords[j] = val\n",
    "    \n",
    "    def __sub__(self, other):\n",
    "        if self.__len__() != len(other):\n",
    "            raise ValueError('Dimensions must agree!!')\n",
    "        else:\n",
    "            result = Vector(self.__len__())\n",
    "            for i in range(self.__len__()):\n",
    "                result[i] = self[i] - other[i]\n",
    "            return result\n",
    "    '''There are many other functions to write'''\n",
    "    def __neg__(self):\n",
    "        result = Vector(self.__len__())\n",
    "        for i in range(self.__len__()):\n",
    "            result[i] = -1 * self[i]\n",
    "        return result\n",
    "    \n",
    "    def __add__(self, other):\n",
    "        if len(self) != len(other):\n",
    "            raise ValueError('Dimensions must agree!!!')\n",
    "        result = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result[j] = self[j] + other[j]\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T07:42:56.184548Z",
     "start_time": "2019-05-21T07:42:56.180533Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, -2, -4, -6]\n"
     ]
    }
   ],
   "source": [
    "v = Vector(4)\n",
    "for i in range(4):\n",
    "    v[i] = 2*i\n",
    "result = v.__neg__()\n",
    "print([result.__getitem__(i) for i in range(4)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2.11)在2.3.3节中，我们注意到Vector类支持形如v=u+[5,3,10,-2,1]这样的语法形式，向量和列表的总和返回一个新的向量。然而，语法v=[5,3,10,-2,1]+u却是非法的。解释应该如何修改Vector类的定义使得上述语法能够生成新的向量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T07:55:14.278321Z",
     "start_time": "2019-05-21T07:55:14.269346Z"
    }
   },
   "outputs": [],
   "source": [
    "class Vector:\n",
    "    \n",
    "    def __init__(self, d):\n",
    "        self._coords = [0]*d\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self._coords)\n",
    "    \n",
    "    def __getitem__(self, j):\n",
    "        return self._coords[j]\n",
    "    \n",
    "    def __setitem__(self, j, val):\n",
    "        self._coords[j] = val\n",
    "    \n",
    "    def __sub__(self, other):\n",
    "        if self.__len__() != len(other):\n",
    "            raise ValueError('Dimensions must agree!!')\n",
    "        else:\n",
    "            result = Vector(self.__len__())\n",
    "            for i in range(self.__len__()):\n",
    "                result[i] = self[i] - other[i]\n",
    "            return result\n",
    "    '''There are many other functions to write'''\n",
    "    def __neg__(self):\n",
    "        result = Vector(self.__len__())\n",
    "        for i in range(self.__len__()):\n",
    "            result[i] = -1 * self[i]\n",
    "        return result\n",
    "    \n",
    "    def __add__(self, other):\n",
    "        if len(self) != len(other):\n",
    "            raise ValueError('Dimensions must agree!!!')\n",
    "        result1 = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result1[j] = self[j] + other[j]\n",
    "        return result1\n",
    "    \n",
    "    def __radd__(self, other):\n",
    "        if len(self) != len(other):\n",
    "            raise ValueError('Dimensions must agree!!!')\n",
    "        result2 = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result2[j] = self[j] + other[j]\n",
    "        return result2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T07:56:19.296078Z",
     "start_time": "2019-05-21T07:56:19.291092Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 5, 14, 4]\n"
     ]
    }
   ],
   "source": [
    "v = Vector(4)\n",
    "for i in range(4):\n",
    "    v[i] = 2*i\n",
    "u = [5,3,10,-2] + v\n",
    "print([u[i] for i in range(4)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2.13)联系R-2.12要求对2.3.3节中的Vector类实现__mul__方法，以提供对语法vx3的支持。试实现__rmul__方法，提供对语法3xv的支持。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T08:05:02.720441Z",
     "start_time": "2019-05-21T08:05:02.708497Z"
    }
   },
   "outputs": [],
   "source": [
    "class Vector:\n",
    "    \n",
    "    def __init__(self, d):\n",
    "        self._coords = [0]*d\n",
    "    \n",
    "    def __len__(self):\n",
    "        return len(self._coords)\n",
    "    \n",
    "    def __getitem__(self, j):\n",
    "        return self._coords[j]\n",
    "    \n",
    "    def __setitem__(self, j, val):\n",
    "        self._coords[j] = val\n",
    "    \n",
    "    def __sub__(self, other):\n",
    "        if self.__len__() != len(other):\n",
    "            raise ValueError('Dimensions must agree!!')\n",
    "        else:\n",
    "            result = Vector(self.__len__())\n",
    "            for i in range(self.__len__()):\n",
    "                result[i] = self[i] - other[i]\n",
    "            return result\n",
    "    '''There are many other functions to write'''\n",
    "    def __neg__(self):\n",
    "        result = Vector(self.__len__())\n",
    "        for i in range(self.__len__()):\n",
    "            result[i] = -1 * self[i]\n",
    "        return result\n",
    "    \n",
    "    def __add__(self, other):\n",
    "        if len(self) != len(other):\n",
    "            raise ValueError('Dimensions must agree!!!')\n",
    "        result_add = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result_add[j] = self[j] + other[j]\n",
    "        return result_add\n",
    "    \n",
    "    def __radd__(self, other):\n",
    "        if len(self) != len(other):\n",
    "            raise ValueError('Dimensions must agree!!!')\n",
    "        result_radd = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result_radd[j] = self[j] + other[j]\n",
    "        return result_radd\n",
    "    \n",
    "    def __mul__(self, val):\n",
    "        result_mul = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result_mul[j] = self[j] * val\n",
    "        return result_mul\n",
    "    \n",
    "    def __rmul__(self, val):\n",
    "        result_rmul = Vector(len(self))\n",
    "        for j in range(len(self)):\n",
    "            result_rmul[j] = self[j] * val\n",
    "        return result_rmul"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T08:05:03.375237Z",
     "start_time": "2019-05-21T08:05:03.370292Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0, 8, 16, 24]\n",
      "[0, 8, 16, 24]\n"
     ]
    }
   ],
   "source": [
    "v = Vector(4)\n",
    "for i in range(4):\n",
    "    v[i] = 2*i\n",
    "u = 4 * v\n",
    "h = v * 4\n",
    "print([u[i] for i in range(4)])\n",
    "print([h[i] for i in range(4)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## (2.18)给出一个来自Python代码的简短片段，使用2.4.2节的Progression类，找到那个以2开始且以2作为前两个值的斐波那契数列的第8个值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 基类——Progression"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T08:19:41.561804Z",
     "start_time": "2019-05-21T08:19:41.555804Z"
    }
   },
   "outputs": [],
   "source": [
    "class Progression:\n",
    "    def __init__(self, start=0):\n",
    "        self._current = start\n",
    "    \n",
    "    def _advance(self):\n",
    "        self._current += 1\n",
    "    \n",
    "    def __next__(self):\n",
    "        if self._current is None:\n",
    "            raise StopIteration()\n",
    "        else:\n",
    "            answer = self._current\n",
    "            self._advance()\n",
    "            return answer\n",
    "    def __iter__(self):\n",
    "        return self\n",
    "    \n",
    "    def print_progression(self, n):\n",
    "        print(' '.join(str(next(self)) for j in range(n)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 子类——FibonacciProgressionTwo(Progression)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T08:39:09.983382Z",
     "start_time": "2019-05-21T08:39:09.975405Z"
    }
   },
   "outputs": [],
   "source": [
    "class FibonacciProgressionTwo(Progression):\n",
    "    \n",
    "    def __init__(self, first=2, second=2):\n",
    "        super().__init__(first)\n",
    "        self._prev = second - first\n",
    "    \n",
    "    def _advance(self):\n",
    "        self._prev, self._current = self._current, self._current+self._prev \n",
    "    \n",
    "    def find_exact_one(self, n):\n",
    "        exact_list = [next(self) for i in range(n)]\n",
    "        exact_one = exact_list[-1]\n",
    "        print(exact_one)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 测试子类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T08:39:11.679959Z",
     "start_time": "2019-05-21T08:39:11.676000Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 2 4 6 10 16 26 42\n"
     ]
    }
   ],
   "source": [
    "FibonacciProgressionTwo().print_progression(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-05-21T08:39:12.798862Z",
     "start_time": "2019-05-21T08:39:12.794874Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "42\n"
     ]
    }
   ],
   "source": [
    "FibonacciProgressionTwo().find_exact_one(8)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
